
import java.text.SimpleDateFormat
import java.time.*
import java.time.format.DateTimeFormatter
import java.time.format.DateTimeParseException
import java.time.temporal.ChronoUnit
import java.util.*


/**
 * @author qins
 * @desc LocalDate, LocalDateTime 转化，格式化相关操作扩展
 */

/********************************************LocalDateTime格式字符串函数************************************/
const val DATE_FORMAT_19= "yyyy-MM-dd HH:mm:ss" // 时间格式19字符
const val DATE_FORMAT_16= "yyyy-MM-dd HH:mm" // 时间格式19字符
const val DATE_FORMAT_23= "yyyy-MM-dd HH:mm:ss.[SSS]" // 时间格式19字符
const val DATE_FORMAT_15= "yyyyMMdd HHmmss" // 时间格式15字符
const val DATE_FORMAT_14= "yyyyMMddHHmmss" // 时间格式14字符
const val DATE_FORMAT_8= "yyyyMMdd" // 时间格式8字符
const val DATE_FORMAT_6= "yyMMdd" // 时间格式6字符
const val DATE_FORMAT_10= "yyyy-MM-dd" // 时间格式10字符
/********************************************Time格式字符串函数************************************/
const val TIME_FORMAT_5= "HH:mm" // 时间格式6字符
const val TIME_FORMAT_8= "HH:mm:ss" // 时间格式6字符

private fun dateFormat(pattern: String, time: LocalDateTime) : String {
    val df = DateTimeFormatter.ofPattern(pattern)
    return df.format(time)
}

private fun dateFormat(pattern: String, date: LocalDate) : String {
    val df = DateTimeFormatter.ofPattern(pattern)
    return df.format(date)
}

/**
 * 将LocalDate格式化成yyMMdd字符串
 */
fun LocalDate.toStringFormat6() : String = dateFormat(DATE_FORMAT_6, this)
/**
 * 将LocalDateTime格式化成yyMMdd字符串
 */
fun LocalDateTime.toStringFormat6() : String = dateFormat(DATE_FORMAT_6, this)
/**
 * 将LocalDate格式化成yyyyMMdd字符串
 */
fun LocalDate.toStringFormat8() : String = dateFormat(DATE_FORMAT_8, this)

/**
 * 将LocalDateTime格式化成yyyyMMdd字符串
 */
fun LocalDateTime.toStringFormat8() : String = dateFormat(DATE_FORMAT_8, this)

/**
 * 将LocalDate格式化成yyyy-MM-dd字符串
 */
fun LocalDate.toStringFormat10() : String = dateFormat(DATE_FORMAT_10, this)

/**
 * 将LocalDateTime格式化成yyyy-MM-dd字符串
 */
fun LocalDateTime.toStringFormat10() : String = dateFormat(DATE_FORMAT_10, this)

/**
 * 将LocalDatTime格式化成yyyyMMddHHmmss字符串
 */
fun LocalDateTime.toStringFormat14() : String = dateFormat(DATE_FORMAT_14, this)

/**
 * 将LocalDatTime格式化成yyyy-MM-dd HH:mm:ss字符串
 */
fun LocalDateTime.toStringFormat19() : String = dateFormat(DATE_FORMAT_19, this)

/**
 * 将LocalDatTime格式化成yyyyMMdd HHmmss字符串
 */
fun LocalDateTime.toStringFormat15() : String = dateFormat(DATE_FORMAT_15, this)

/**
 * 将LocalDatTime格式化成yyyy-MM-dd HH:mm:ss.[SSS]字符串
 */
fun LocalDateTime.toStringFormat23() : String = dateFormat(DATE_FORMAT_23, this)

/**
 * 将字符串yyyy-MM-dd HH:mm 转LocalDateTime
 */
fun String?.format16ToLocalDateTime(): LocalDateTime? {
    if(this.isNullOrBlank()) return null
    var date: LocalDateTime? = null
    if(DATE_FORMAT_16.length != this.length) {
        return null
    }
    try {
        date = LocalDateTime.parse(this, DateTimeFormatter.ofPattern(DATE_FORMAT_16))
    } catch (e: DateTimeParseException) {
        e.printStackTrace()
    }
    return date
}

/**
 * 将字符串yyyy-MM-dd HH:mm:ss 转LocalDateTime
 */
fun String?.format19ToLocalDateTime(): LocalDateTime? {
    if(this.isNullOrBlank()) return null
    var date: LocalDateTime? = null
    if(DATE_FORMAT_19.length != this.length) {
        return null
    }
    try {
        date = LocalDateTime.parse(this, DateTimeFormatter.ofPattern(DATE_FORMAT_19))
    } catch (e: DateTimeParseException) {
        e.printStackTrace()
    }
    return date
}

/**
 * yyyy-MM-dd 转 LocalDateTime yyyy-MM-dd 00:00:00
 */
fun String?.format10ToLocalDateTime(): LocalDateTime? {
    if(this.isNullOrBlank()) return null
    var date: LocalDateTime? = null
    var str = this
    if(DATE_FORMAT_10.length == this.length) {
        str += " 00:00:00"
    }
    try {
        date = LocalDateTime.parse(str, DateTimeFormatter.ofPattern(DATE_FORMAT_19))
    } catch (e: DateTimeParseException) {
        e.printStackTrace()
    }
    return date
}


/**
 * yyyyMMdd 转 LocalDateTime
 */
fun String?.format8ToLocalDateTime(): LocalDateTime? {
    if(this.isNullOrBlank()) return null
    var date: LocalDateTime? = null
    try {
        date = LocalDateTime.parse("$this 00:00:00", DateTimeFormatter.ofPattern("$DATE_FORMAT_8 HH:mm:ss"))
    } catch (e: DateTimeParseException) {
        e.printStackTrace()
    }
    return date
}
/**
 * yyyy-MM-dd 转 LocalDate
 */
fun String?.format10ToLocalDate(): LocalDate? {
    if(this.isNullOrBlank()) return null
    var date: LocalDate? = null
    try {
        date = LocalDate.parse(this, DateTimeFormatter.ofPattern(DATE_FORMAT_10))
    } catch (e: DateTimeParseException) {
        e.printStackTrace()
    }
    return date
}
/**
 * yyyyMMdd 转 LocalDate
 */
fun String?.format8ToLocalDate(): LocalDate? {
    if(this.isNullOrBlank()) return null
    var date: LocalDate? = null
    try {
        date = LocalDate.parse(this, DateTimeFormatter.ofPattern(DATE_FORMAT_8))
    } catch (e: DateTimeParseException) {
        e.printStackTrace()
    }
    return date
}
/**
 * HH:mm 转 LocalTime
 */
fun String?.format5ToLocalTime(): LocalTime? {
    if(this.isNullOrBlank()) return null
    var time: LocalTime? = null
    try {
        time = LocalTime.parse(this, DateTimeFormatter.ofPattern(TIME_FORMAT_5))
    } catch (e: DateTimeParseException) {
        e.printStackTrace()
    }
    return time
}

/**
 * HH:mm:ss 转 LocalTime
 */
fun String?.format8ToLocalTime(): LocalTime? {
    if(this.isNullOrBlank()) return null
    var time: LocalTime? = null
    try {
        time = LocalTime.parse(this, DateTimeFormatter.ofPattern(TIME_FORMAT_8))
    } catch (e: DateTimeParseException) {
        e.printStackTrace()
    }
    return time
}




/**
 * 字符串日期格式化成yyyy-MM-dd
 */
fun String?.format10ToString() : String? {
    if(this.isNullOrBlank() || this.length < DATE_FORMAT_10.length) {
        return this
    }
    return this.substring(0, 10)
}

/**
 * 字符串日期格式化成yyyy-MM-dd
 */
fun String?.format19ToString() : String? {
    if(this.isNullOrBlank() || this.length < DATE_FORMAT_19.length) {
        return this
    }
    return this.substring(0, 19)
}
/**
 * 将字符串yyyy-MM-dd HH:mm:ss 转Date ---只对必要框架里边的转换使用，其余的都用LocalDateTime
 */
fun String?.format19ToDate(): Date? {
    if(this.isNullOrBlank()) return null
    var date: Date? = null
    if(DATE_FORMAT_19.length != this.length) {
        return null
    }
    try {
        val sdf = SimpleDateFormat(DATE_FORMAT_19)
        date = sdf.parse(this)
    } catch (e: DateTimeParseException) {
        e.printStackTrace()
    }
    return date
}

/**
 * yyyy-MM-dd 转 Date yyyy-MM-dd  ---只对必要框架里边的转换使用，其余的都用LocalDate
 */
fun String?.format10ToDate(): Date? {
    if(this.isNullOrBlank()) return null
    var date: Date? = null
    if(DATE_FORMAT_10.length != this.length) {
        return null
    }
    try {
        val sdf = SimpleDateFormat(DATE_FORMAT_10)
        date = sdf.parse(this)
    } catch (e: DateTimeParseException) {
        e.printStackTrace()
    }
    return date
}


/**
 * 转为一天中最开始的时刻 0:00
 */
fun LocalDate?.toLocalDateTimeStartOfDay() : LocalDateTime? {
    if(this == null) return this
    return LocalDateTime.of(this, LocalTime.MIN)
}
/**
 * 转为一天中最晚的时刻 23:59:59
 */
fun LocalDate?.toLocalDateTimeEndOfDay() : LocalDateTime? {
    if(this == null) return this
    return LocalDateTime.of(this, LocalTime.MAX)
}

/**
 * Date转LocalDateTime
 */
fun Date?.toLocalDateTime(): LocalDateTime? {
    if(this == null) return this
    return this.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime()
}

/**
 * Date转LocalDateTime
 */
fun Date?.toLocalDateTimeString(): String? {
    if(this == null) return this
    return this.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime().toStringFormat19()
}
/**
 * 获取对比的两个时间中大的时间
 */
fun LocalDateTime.getMaxLocalDateTime(localDateTime: LocalDateTime?) : LocalDateTime {
    localDateTime ?: return this
    return if(this.isBefore(localDateTime)) localDateTime else this

}

/**
 * 获取对比的两个时间中小的时间
 */
fun LocalDateTime.getMiLocalDateTime(localDateTime: LocalDateTime?) : LocalDateTime {
    localDateTime ?: return this
    return if(this.isBefore(localDateTime)) this else localDateTime

}

/**
 * 获取明天凌晨0:0:0与当前时间相差的秒数
 * 主要用于设置redis key只在当天有效 半夜
 */
fun getDiffSecondMidnight() : Long = ChronoUnit.SECONDS.between(LocalDateTime.now(), LocalDate.now().plusDays(1).atStartOfDay())


/**
 * 毫秒时间戳转LocalDateTime
 */
fun Long.millsToLocalDateTime() : LocalDateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(this), ZoneId.systemDefault())
